﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace zj.Communicationlib.ByteArrays
{
    public static class ByteArrayHelper
    {
        /// <summary>
        /// 比较前n个字节的数组是否相同
        /// </summary>
        /// <param name="byteArray1"></param>
        /// <param name="byteArray2"></param>
        /// <param name="length">比较的字节数</param>
        /// <returns></returns>
        public static bool ByteArrayCompare(ByteArray byteArray1, ByteArray byteArray2, int length)
        {
            if (byteArray1 == null || byteArray2 == null) return false;
            if (byteArray1.Length < length || byteArray2.Length < length) return false;
            for (int i = 0; i < length; i++)
            {
                if (byteArray1[i] != byteArray2[i])
                {
                    return false;
                }

            }
            return true;
        }
        /// <summary>
        /// 比较两个字节是否完全相同
        /// </summary>
        /// <param name="byteArray1"></param>
        /// <param name="byteArray2"></param>
        /// <returns></returns>
        public static bool ByteArrayCompare(ByteArray byteArray1, ByteArray byteArray2)
        {
            if (byteArray1 == null || byteArray2 == null) return false;
            if (byteArray1.Length == byteArray2.Length)
            {
                int byteLength = byteArray1.Length;
                for (int i = 0; i < byteLength; i++)
                {
                    if (byteArray1[i] != byteArray2[i])
                    {
                        return false;
                    }

                }

            }
            else
            {
                return false;
            }
            return true;

        }
        /// <summary>
        /// 比较前n个字节的数组是否相同
        /// </summary>
        /// <param name="byteArray1"></param>
        /// <param name="byteArray2"></param>
        /// <param name="startIndex">起始索引号</param>
        /// <param name="length">比较的字节数</param>
        /// <returns></returns>
        public static bool ByteArrayCompare(ByteArray byteArray1, ByteArray byteArray2, int startIndex, int length)
        {
            if (byteArray1 == null || byteArray2 == null) return false;
            if (byteArray1.Length < (length + startIndex) || byteArray2.Length < (length + startIndex)) return false;
            for (int i = startIndex; i < startIndex + length; i++)
            {
                if (byteArray1[i] != byteArray2[i])
                {
                    return false;
                }

            }
            return true;
        }
        /// <summary>
        /// 字节数组转换为布尔数组
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="length">布尔数组的长度</param>
        /// <returns></returns>
        public static bool[] ByteArrayToBoolArray(byte[] bytes, int length)
        {
            bool[] results = new bool[length];
            BitArray bitArray = new BitArray(bytes);
            for (int i = 0; i < length; i++)
            {
                results[i] = bitArray[i];
            }
            return results;
        }
        /// <summary>
        /// 布尔数组转字节数组
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static ByteArray BoolArrayToByteArray(bool[] values)
        {
            int length = values.Length % 8 == 0 ? values.Length / 8 : values.Length / 8 + 1;
            ByteArray byteArray = new ByteArray();
            byte[] result = new byte[length];
            for (int i = 0; i < values.Length; i++)
            {
                int j = i % 8;
                int index = i / 8;
                result[index] = ByteSetBit(result[index], j, values[i]);
            }
            byteArray.AddRange(result);
            return byteArray;


        }
        /// <summary>
        /// 对一个字节内设置某个位的值
        /// </summary>
        /// <param name="byteValue">字节</param>
        /// <param name="bitIndex">位索引</param>
        /// <param name="bitValue">布尔值</param>
        /// <returns></returns>
        private static byte ByteSetBit(byte byteValue, int bitIndex, bool bitValue)
        {

            if (bitValue)
            {
                byteValue |= (byte)Math.Pow(2, bitIndex);
            }
            else
            {
                byteValue &= (byte)~Convert.ToInt32(Math.Pow(2, bitIndex));
            }
            return byteValue;
        }
        ///// <summary>
        ///// 32位整型转换为4个字节数组
        ///// </summary>
        ///// <param name="value"></param>
        ///// <param name="registerFormat"></param>
        ///// <returns></returns>
        //public static byte[] UintToByteArray(uint value, RegisterFormat registerFormat = RegisterFormat.ABCD)
        //{
        //    byte[] resultABCD = BitConverter.GetBytes(value).Reverse().ToArray();    //ABCD
        //    byte[] resultDCBA = BitConverter.GetBytes(value);         //DCBA
        //    byte[] Hbytes = new byte[2];           //AB
        //    byte[] Lbytes = new byte[2];           //CD
        //    Array.Copy(resultDCBA, 0, Hbytes, 0, 2);  //AB
        //    Array.Copy(resultDCBA, 2, Lbytes, 0, 2);  //CD
        //    byte[] HbyteSwap = Hbytes.Reverse().ToArray();            //BA
        //    byte[] LbyteSwap = Lbytes.Reverse().ToArray();            //DC
        //    if (registerFormat == RegisterFormat.ABCD)
        //    {
        //        return resultABCD;
        //    }
        //    else if (registerFormat == RegisterFormat.DCBA)
        //    {
        //        return resultDCBA;
        //    }
        //    else if (registerFormat == RegisterFormat.BADC)
        //    {
        //        return Lbytes.Union(Hbytes).ToArray();         //BADC
        //    }
        //    else
        //    {

        //        return HbyteSwap.Union(LbyteSwap).ToArray();   // CDAB
        //    }
        //}
        //public static byte[] IntToByteArray(int value, RegisterFormat registerFormat = RegisterFormat.ABCD)
        //{
        //    byte[] resultABCD = BitConverter.GetBytes(value).Reverse().ToArray();    //ABCD
        //    byte[] resultDCBA = BitConverter.GetBytes(value);         //DCBA
        //    byte[] Hbytes = new byte[2];           //AB
        //    byte[] Lbytes = new byte[2];           //CD
        //    Array.Copy(resultDCBA, 0, Hbytes, 0, 2);  //AB
        //    Array.Copy(resultDCBA, 2, Lbytes, 0, 2);  //CD
        //    byte[] HbyteSwap = Hbytes.Reverse().ToArray();            //BA
        //    byte[] LbyteSwap = Lbytes.Reverse().ToArray();            //DC
        //    if (registerFormat == RegisterFormat.ABCD)
        //    {
        //        return resultABCD;
        //    }
        //    else if (registerFormat == RegisterFormat.DCBA)
        //    {
        //        return resultDCBA;
        //    }
        //    else if (registerFormat == RegisterFormat.BADC)
        //    {
        //        return Lbytes.Union(Hbytes).ToArray();         //BADC
        //    }
        //    else
        //    {

        //        return HbyteSwap.Union(LbyteSwap).ToArray();   // CDAB
        //    }
        //}

        /// <summary>
        /// 值类型转换位字节数组类型
        /// </summary>
        /// <param name="value"></param>
        /// <param name="registerFormat"></param>
        /// <returns></returns>
        public static byte[] GetByteArray<T>(this T value, Func<T, byte[]> func, RegisterFormat registerFormat = RegisterFormat.ABCD)
            where T : struct
        {

            List<byte> bytesReverse = new List<byte>();     //字节逆序排列的集合
            byte[] result = func.Invoke(value);             //获取数值的字节数组
            int length = result.Length;
            for (int i = 0; i < length; i += 2)
            {
                byte[] tempByte = new byte[2];
                Array.Copy(result, i, tempByte, 0, 2);  //AB
                bytesReverse.AddRange(tempByte.Reverse().ToArray());
            }

            if (registerFormat == RegisterFormat.ABCD)
            {
                return result;
            }
            else if (registerFormat == RegisterFormat.BADC)
            {
                return bytesReverse.ToArray();
            }
            else if (registerFormat == RegisterFormat.DCBA)
            {
                return result.Reverse().ToArray(); ;
            }
            else
            {
                bytesReverse.Reverse();
                return bytesReverse.ToArray();
            }



        }
        /// <summary>
        /// 字节数组类型转换位值类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="values"></param>
        /// <param name="func"></param>
        /// <param name="registerFormat"></param>
        /// <returns></returns>
        public static T GetT<T>(byte[] values, Func<byte[], T> func, RegisterFormat registerFormat = RegisterFormat.ABCD)
            where T : struct
        {

            List<byte> bytesReverse = new List<byte>();
            int length = values.Length;
            byte[] resultByte = null;
            for (int i = 0; i < length; i += 2)
            {
                byte[] tempByte = new byte[2];

                Array.Copy(values, i, tempByte, 0, 2);  //AB

                bytesReverse.AddRange(tempByte.Reverse().ToArray());

            }

            if (registerFormat == RegisterFormat.ABCD)
            {
                resultByte = values;
            }
            else if (registerFormat == RegisterFormat.BADC)
            {
                resultByte = bytesReverse.ToArray();
            }
            else if (registerFormat == RegisterFormat.DCBA)
            {
                resultByte = values.Reverse().ToArray();
            }
            else
            {
                bytesReverse.Reverse();
                resultByte = bytesReverse.ToArray();
            }
            return func.Invoke(resultByte);
        }
    }
}
